package net.tomblog.app.swingheil.oauth;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;

import net.tomblog.app.swingheil.model.AccessToken;
import net.tomblog.app.swingheil.oauth.OAuthDialog.OAuthDialogListener;
import net.tomblog.app.swingheil.util.L;
import oauth.signpost.OAuthProvider;
import oauth.signpost.basic.DefaultOAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;

/**
 * OAuth 인증관련 처리를 담당하는 클래스
 * 
 * @author hyunung.park (parkbear01@gmail.com)
 * 
 */
public class SwingHeilOAuth {

	private static final String TAG = "OAuth";

	public static final String NAVER = "naver";
	public static final String DAUM = "daum";
	public static final String TWITTER = "twitter";

	public static final String NAVER_CONSUMER_KEY = "6eb_KtTH6Jjx";
	public static final String NAVER_CONSUMER_SECRET = "4E928A58A2iAueBz4Mdx";
	public static final String NAVER_REQUEST_TOKEN_URL = "https://nid.naver.com/naver.oauth?mode=req_req_token";
	public static final String NAVER_AUTHORIZE_URL = "https://nid.naver.com/naver.oauth?mode=auth_req_token";
	public static final String NAVER_ACCESS_TOKEN_URL = "https://nid.naver.com/naver.oauth?mode=req_acc_token";
	public static final String MY_NAVER_ACCESS_TOKEN = "q48rfBju3JzbzlXsbu5RaJHjP4n6wJ";
	public static final String MY_NAVER_TOKEN_SECRET = "g2aApZJNRaBTTlELNIUJyTZoMGjY8x";
	

	public static final String DAUM_CONSUMER_KEY = "ab4df9c0-9c43-46aa-90e9-94b4dbdfbf34";
	public static final String DAUM_CONSUMER_SECRET = "WAPuHjhY61TBFiw6e.NeRclem1DS9ZDwWVoQSqS.eHrOW9oK51uEUA00";
	public static final String DAUM_REQUEST_TOKEN_URL = "https://apis.daum.net/oauth/requestToken";
	public static final String DAUM_AUTHORIZE_URL = "https://apis.daum.net/oauth/authorize";
	public static final String DAUM_ACCESS_TOKEN_URL = "https://apis.daum.net/oauth/accessToken";
	public static final String MY_DAUM_ACCESS_TOKEN = "988ce7b5-a1a0-4fa6-bead-1e4d47641d7c";
	public static final String MY_DAUM_TOKEN_SECRET = "TnandmcqzTIWWPYaAyjwL-Y1sjOUYvS9TXjvLsx3G9h7r1.OsiqOsA00";

	public static final String TWITTER_CONSUMER_KEY = "CLYzYAeAgwBq9cPXzXWjg";
	public static final String TWITTER_CONSUMER_SECRET = "SOndT1quCUwl2HWW7QBnmgTnvrG5oLykUI4BJkhxLHk";
	public static final String TWITTER_REQUEST_TOKEN_URL = "https://api.twitter.com/oauth/request_token";
	public static final String TWITTER_AUTHORIZE_URL = "https://api.twitter.com/oauth/authorize";
	public static final String TWITTER_ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";

	public static final int MSG_ERROR_GETTING_REQUEST_TOKEN = 1;
	public static final int MSG_ERROR_GETTING_ACCESS_TOKEN = 2;
	public static final int MSG_SHOW_LOGIN_DIALOG = 3;
	public static final int MSG_GOT_ACCESS_TOKEN = 4;

	public static final String CALLBACK_URL = "http://www.tomblog.net";

	private Context mContext;
	private ProgressDialog mProgressDlg;
	private OAuthPreference mOAuthPref;
	private CommonsHttpOAuthConsumer mHttpOauthConsumer;
	private OAuthProvider mOAuthprovider;
	private String mConsumerKey;
	private String mSecretKey;
	private String mProviderName;
	private OAuthListener mOAuthListener;

	private AccessToken mAccessToken;
	
	public SwingHeilOAuth(Context context, String providerName, OAuthListener oAuthListener) {
		mContext = context;
		mProviderName = providerName;
		mOAuthListener = oAuthListener;

		mOAuthPref = new OAuthPreference(context);
		setConsumerAndSecretKey(providerName);
		mHttpOauthConsumer = new CommonsHttpOAuthConsumer(mConsumerKey, mSecretKey);
		mOAuthprovider = getDefaultOAuthProvider(providerName);

		mProgressDlg = new ProgressDialog(context);
		mProgressDlg.requestWindowFeature(Window.FEATURE_NO_TITLE);
	}

	private Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			mProgressDlg.dismiss();

			switch (msg.what) {
			case MSG_ERROR_GETTING_REQUEST_TOKEN:
				L.d(TAG, "mHandler >>> MSG_ERROR_GETTING_REQUEST_TOKEN");
				mOAuthListener.onError(mProviderName, MSG_ERROR_GETTING_REQUEST_TOKEN);
				break;
			case MSG_ERROR_GETTING_ACCESS_TOKEN:
				L.d(TAG, "mHandler >>> MSG_ERROR_GETTING_ACCESS_TOKEN");
				mOAuthListener.onError(mProviderName, MSG_ERROR_GETTING_ACCESS_TOKEN);
				break;
			case MSG_SHOW_LOGIN_DIALOG:
				L.d(TAG, "mHandler >>> MSG_SHOW_LOGIN_DIALOG");
				showLoginDialog((String) msg.obj);
				break;
			case MSG_GOT_ACCESS_TOKEN:
				L.d(TAG, "mHandler >>> MSG_GOT_ACCESS_TOKEN");
				mOAuthListener.onComplete(mProviderName, MSG_GOT_ACCESS_TOKEN);
				break;
			default:
				break;
			}
		}
	};

	public void authorize() {
		L.d(TAG, " >>> called authorize()");

		mProgressDlg.setMessage("Initializing ...");
		mProgressDlg.show();

		new Thread() {
			@Override
			public void run() {
				String authUrl = null;
				int what = 0;

				try {
					authUrl = mOAuthprovider.retrieveRequestToken(mHttpOauthConsumer, CALLBACK_URL);
					L.d(TAG, "Request token url at first trial : " + authUrl);

					what = MSG_SHOW_LOGIN_DIALOG;
				} catch (Exception e) {
					L.d(TAG, "Failed to get request token at first trial.");
					what = MSG_ERROR_GETTING_REQUEST_TOKEN;
					e.printStackTrace();
				}
				
				mHandler.sendMessage(mHandler.obtainMessage(what, authUrl));
			}
		}.start();
	}

	public void processToken(String callbackUrl) {
		L.d(TAG, " >>> called processToken()");
		mProgressDlg.setMessage("Finalizing ...");
		mProgressDlg.show();

		final String verifier = getVerifier(callbackUrl);

		new Thread() {
			@Override
			public void run() {
				int what = MSG_ERROR_GETTING_ACCESS_TOKEN;
				
				L.d(TAG, "getConsumerKey : " + mHttpOauthConsumer.getConsumerKey());
				L.d(TAG, "getConsumerSecret : " + mHttpOauthConsumer.getConsumerSecret());
				L.d(TAG, "getToken : " + mHttpOauthConsumer.getToken());
				L.d(TAG, "getTokenSecret : " + mHttpOauthConsumer.getTokenSecret());

				try {
					mOAuthprovider.retrieveAccessToken(mHttpOauthConsumer, verifier);

					mAccessToken = new AccessToken(mHttpOauthConsumer.getToken(), mHttpOauthConsumer.getTokenSecret());
					mOAuthPref.storeAccessToken(mAccessToken, mProviderName);
					what = MSG_GOT_ACCESS_TOKEN;
					
					if(mAccessToken != null) {
						Log.e(TAG, "Access token1 : " + mAccessToken.toString());
					}
				} catch (Exception e) {
					Log.e(TAG, "Error getting access token at first trial.");
					e.printStackTrace();
				}
									
				mHandler.sendMessage(mHandler.obtainMessage(what));
			}
		}.start();
	}

	private String getVerifier(String callbackUrl) {
		L.d(TAG, " >>> called getVerifier(), callbackUrl : " + callbackUrl);
		String verifier = "";

		try {
			URL url = new URL(callbackUrl);
			String query = url.getQuery();

			String array[] = query.split("&");

			for (String parameter : array) {
				String v[] = parameter.split("=");

				if (URLDecoder.decode(v[0]).equals(
						oauth.signpost.OAuth.OAUTH_VERIFIER)) {
					verifier = URLDecoder.decode(v[1]);
					break;
				}
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}

		L.d(TAG, "verifier : " + verifier);
		return verifier;
	}

	private void showLoginDialog(String url) {
		final OAuthDialogListener listener = new OAuthDialogListener() {
			private static final String TAG = "OAuthDialogListener";
			
			@Override
			public void onComplete(String value) {
				L.d(TAG, " >>> called onComplete()");
				processToken(value);
			}

			@Override
			public void onError(String value) {
				L.d(TAG, " >>> called onError()");
			}
		};

		new OAuthDialog(mContext, url, listener, mProviderName).show();
	}

	private void setConsumerAndSecretKey(String providerName) {
		if (providerName.equals(NAVER)) {
			mConsumerKey = NAVER_CONSUMER_KEY;
			mSecretKey = NAVER_CONSUMER_SECRET;
		} else if (providerName.equals(DAUM)) {
			mConsumerKey = DAUM_CONSUMER_KEY;
			mSecretKey = DAUM_CONSUMER_SECRET;
		} else if (providerName.equals(TWITTER)) {
			mConsumerKey = TWITTER_CONSUMER_KEY;
			mSecretKey = TWITTER_CONSUMER_SECRET;
		}
	}

	private DefaultOAuthProvider getDefaultOAuthProvider(String providerName) {
		String requestTokenURL = null;
		String accessTokenURL = null;
		String authorizeURL = null;

		if (providerName.equals(NAVER)) {
			requestTokenURL = NAVER_REQUEST_TOKEN_URL;
			accessTokenURL = NAVER_ACCESS_TOKEN_URL;
			authorizeURL = NAVER_AUTHORIZE_URL;
		} else if (providerName.equals(DAUM)) {
			requestTokenURL = DAUM_REQUEST_TOKEN_URL;
			accessTokenURL = DAUM_ACCESS_TOKEN_URL;
			authorizeURL = DAUM_AUTHORIZE_URL;
		} else if (providerName.equals(TWITTER)) {
			requestTokenURL = TWITTER_REQUEST_TOKEN_URL;
			accessTokenURL = TWITTER_ACCESS_TOKEN_URL;
			authorizeURL = TWITTER_AUTHORIZE_URL;
		}

		DefaultOAuthProvider oauthProvider = new DefaultOAuthProvider(
				requestTokenURL, accessTokenURL, authorizeURL);

		return oauthProvider;
	}

	public boolean hasAccessToken(String providerName) {
		AccessToken accessToken = mOAuthPref.getAccessToken(providerName);
		if(accessToken == null) {
			L.d(TAG, providerName + "accessToken : null");
			return false;
		}else {
			L.d(TAG, providerName + "accessToken : " + accessToken.toString());
			return true;
		}
	}

	public void resetAccessToken(String providerName) {
		mOAuthPref.resetAccessToken(providerName);
	}

	public void changeProvider(String providerName) {
		mProviderName = providerName;
		setConsumerAndSecretKey(providerName);
		mHttpOauthConsumer = new CommonsHttpOAuthConsumer(mConsumerKey, mSecretKey);
		mOAuthprovider = getDefaultOAuthProvider(providerName);
	}
	
	public interface OAuthListener {
		public void onComplete(String providerName, int resultCode);

		public void onError(String providerName, int resultCode);
	}
}